#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
#=== Summary
# Parses command-line options.

require 'optparse'
module Trepan
  require 'rubygems'; require 'require_relative'
  require_relative 'default'

  VERSION = '0.1.6' unless defined? Trepan::VERSION
  PROGRAM = 'trepan8' unless defined? Trepan::PROGRAM

  module_function

  def show_version
    "#{PROGRAM}, version #{VERSION}"
  end

  def copy_default_options
    options = {}
    DEFAULT_CMDLINE_SETTINGS.each do |key, value|
      begin
        options[key] = value.clone
      rescue TypeError
        options[key] = value
      end
    end
    options
  end

  def setup_options(options, stdout=$stdout, stderr=$stderr)
    OptionParser.new do |opts|
      opts.banner = <<EOB
#{show_version}
Usage: #{PROGRAM} [options] [[--] <script.rb> <script.rb parameters>]
EOB
      opts.separator ''
      opts.separator 'Options:'
      opts.on('--client',
              'Connect to out-of-process program') do
        if options[:server]
          stderr.puts '--server option previously given. --client option ignored.'
        else
          options[:client] = true
        end
      end
      opts.on('-c', '--command FILE', String,
              'Execute debugger commands from FILE') do |cmdfile|
        if File.readable?(cmdfile)
          options[:cmdfiles] << cmdfile
        elsif File.exists?(cmdfile)
            stderr.puts "Command file '#{cmdfile}' is not readable. Option ignored."
        else
          stderr.puts "Command file '#{cmdfile}' does not exist."
        end
      end
      opts.on('--cd DIR', String, 'Change current directory to DIR') do |dir|
        if File.directory?(dir)
          if File.executable?(dir)
            options[:chdir] = dir
          else
            stderr.puts "Can't cd to #{dir}. Option --cd ignored."
          end
        else
          stderr.puts "\"#{dir}\" is not a directory. Option --cd ignored."
        end
      end
      opts.on('--basename',
              'Show only file basename in file locations') do
        options[:basename] = true
      end
      opts.on('-d', '--debug', 'Set $DEBUG=true') do
        $DEBUG = true
      end
      opts.on('--cport PORT', Integer, 'Port used for control commands') do
        |cport|
        options[:cport] = cport
      end
      opts.on('--[no-]highlight',
              'Use [no] syntax highlight output') do |v|
        options[:highlight] = ((v) ? :term : nil)
        if options[:highlight]
          begin
            require 'linecache'
          rescue LoadError
            require 'linecache19'
          end
          unless LineCache.respond_to?(:clear_file_format_cache)
            stderr.puts "Your version of LineCache doesn't support terminal highlight"
            options[:higlight] = false
          end
        end
      end
      opts.on('-h', '--host NAME', String,
              'Host or IP used in TCP connections for --server or --client. ' +
              "Default is #{DEFAULT_SETTINGS[:host].inspect}.") do
        |name_or_ip|
        options[:host] = name_or_ip
      end
      opts.on('-I', '--include PATH', String, 'Add PATH to $LOAD_PATH') do |path|
        $LOAD_PATH.unshift(path)
      end
      opts.on('--keep-frame-binding', 'Keep frame bindings') do
        options[:frame_bind] = true
      end
      opts.on('-m', '--post-mortem', 'Activate post-mortem mode') do
        options[:post_mortem] = true
      end
      opts.on('--nx',
              "Do not run debugger initialization file #{CMD_INITFILE}") do
        options[:nx] = true
      end
      opts.on('--[no-]control', 'Start [not] control thread') do |v|
        options[:control] = v
      end
      opts.on('-p', '--port NUMBER', Integer,
              'Port number used in TCP connections for --server or --client. ' +
              "Default is #{DEFAULT_SETTINGS[:port]}.") do
        |num|
        options[:port] = num
      end
      opts.on('--[no-]quit', 'Do [not] quit when script finishes') do |v|
        options[:quit] = v
      end
      opts.on('--[no-]readline',
              'Try [not] GNU Readline') do |v|
        options[:readline] = v
      end
      opts.on('-r', '--require SCRIPT', String,
              'Require the library, before executing your script') do |name|
        if name == 'debug'
          stderr.puts "trepan8 is not compatible with Ruby's 'debug' library. This option is ignored."
        else
          require name
        end
      end
      opts.on('--[no-]rewrite-program',
              'Do not set $0 to the program being debugged') do |v|
        options[:rewrite_program] = v
      end
      opts.on('--[no-]stop', 'Do not stop when script is loaded') do |v|
        options[:stop] = v
      end
      opts.on('--script FILE', String, 'Name of the script file to run') do
        |script|
        options[:script] = script
        unless File.exists?(options[:script])
          stderr.puts "Script file '#{options[:script]}' is not found"
          exit 10
        end
      end
      opts.on('-s', '--server',
              'Set up for out-of-process debugging') do
        if options[:client]
          stderr.puts '--client option previously given. --server option ignored.'
        else
          options[:server] = true
        end
      end
      opts.on('-w', '--wait', 'Wait for a client connection; implies -s option') do
        options[:wait] = true
      end
      opts.on('-x', '--trace', 'Turn on line tracing') do
        options[:traceprint] = true
        options[:nx] = true
      end
      opts.separator ''
      opts.on_tail('-?', '--help', 'Show this message') do
        options[:help] = true
        stdout.puts opts
        exit
      end
      opts.on_tail('-v', '--version',
                   'print the version') do
        options[:version] = true
        stdout.puts show_version
      end
    end
  end
end

if __FILE__ == $0
  include Trepan
  opts = {}
  options ={}
  [%w(--help), %w(--version)].each do |o|
    options = Trepan::copy_default_options
    opts    = Trepan::setup_options(options)
    rest    = opts.parse o
    p options
    puts '=' * 10
  end
  rest = opts.parse! ARGV
  puts opts
  puts '=' * 10
  p options
  puts '=' * 10
  p Trepan::DEFAULT_CMDLINE_SETTINGS
end
